package detect;

import interfaces.Detect;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import models.DS_IPRangeModel;
import models.JavaCommandLineServiceAccounts;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import util.CatchLanguage;
import util.ExecCmdHandle;
import util.Utils;
import entities.Domain;
import entities.IPRange;

public class DetectCDNWebserver implements Detect {

	private static final Logger log = Logger.getLogger(DetectCDNWebserver.class
			.getName());

	@SuppressWarnings("unchecked")
	@Override
	public void getInfo(Map<String, Object> obj) {
		Domain d = (Domain) obj.get("domain");
		try {
			// Load Header
			Map<String, String> mapHeader;
			if (obj.containsKey("mapHeader_240187")) {
				mapHeader = (Map<String, String>) obj.get("mapHeader_240187");
			} else {
				mapHeader = CatchLanguage.loadMapHeader(d);
				obj.put("mapHeader_240187", mapHeader);
			}
			process(d, mapHeader);
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			log.warning(e.getMessage());
		}
	}

	public static void process(Domain d, Map<String, String> mapHeader)
			throws URISyntaxException {
		// Check if server have cloudflare -> cloudflare service
		String serverHeader = mapHeader.get("Server");
		if (serverHeader.toLowerCase().contains("cloudflare")) {
			d.setCdnServer("CloudFlare");
		} else {
			// Get map image source
			Document doc = Jsoup.parse(d.getHtml());
			Map<String, Integer> mapImgSrc = new HashMap<String, Integer>();

			for (Element e : doc.select("img")) {
				String str = e.attr("src");
				URI uri = null;
				try {
					uri = new URI(str);
				} catch (Exception e2) {
					continue;
				}
				if (uri != null) {
					str = uri.getHost();
					if (str != null) {
						str = str.startsWith("www.") ? str.substring(4) : str;
						if (mapImgSrc.containsKey(str)) {
							int currentCount = mapImgSrc.get(str);
							currentCount += 1;
							mapImgSrc.put(str, currentCount);
						} else {
							mapImgSrc.put(str, 1);
						}
					}
				}
			}

			// Calculate most use image source
			String mostUseKey = "";
			int mostUseKeyValue = 0;
			if (mapImgSrc.size() > 0) {
				for (Entry<String, Integer> entry : mapImgSrc.entrySet()) {
					String key = entry.getKey();
					int value = entry.getValue();
					if (value > mostUseKeyValue) {
						mostUseKeyValue = value;
						mostUseKey = key;
					}
				}
			}

			// Get Dig result and CDN WebServer IP
			String domainName = mostUseKey;
			String digResult = ExecCmdHandle.processCommand("dig " + domainName
					+ " A +short");
			String cdnIP = "";

			if (digResult != null && digResult.length() > 0) {
				String[] tempArr = digResult.split("\\n|\\r");
				for (String tempStr : tempArr) {
					if (Utils.isIPAddress(tempStr)) {
						cdnIP = tempStr;
						break;
					}
				}
			}

			// Process Who is by WebServer IP and get NetName Name, Org Name
			if (cdnIP.length() > 0) {

				String whoisByIPResult = "";
				boolean existIP = false;

				// Have to check if this ip is beetwen some IPRange,
				Double ipLong = Utils.ipToLong(cdnIP);
				IPRange ipRange = DS_IPRangeModel.checkIPInRange(ipLong);
				if (ipRange != null && ipRange.getWhois().length() > 0) {
					existIP = true;
				}

				if (existIP) {
					// if true, just get IP whois from database
					whoisByIPResult = ipRange.getWhois();
					existIP = true;
				} else {
					// else process cmd
					whoisByIPResult = ExecCmdHandle.processCommand("whois "
							+ cdnIP);
				}

				if (whoisByIPResult != null && whoisByIPResult.length() > 0) {
					// Get NetName value
					String netName = "";
					Pattern p = Pattern.compile("NetName:[^\\n]+[\n]{1}");
					Matcher m = p.matcher(whoisByIPResult);
					while (m.find()) {
						String match = m.group();
						netName = match.replaceAll("\\n", "");
					}

					// Get Net Range Value
					String netRange = "";
					p = Pattern.compile("NetRange:[^\\n]+[\n]{1}");
					m = p.matcher(whoisByIPResult);
					while (m.find()) {
						String match = m.group();
						netRange = match.replaceAll("\\n", "");
					}

					// Get Org Name Value
					@SuppressWarnings("unused")
					String orgName = "";
					p = Pattern.compile("OrgName:[^\\n]+[\n]{1}");
					m = p.matcher(whoisByIPResult);
					while (m.find()) {
						String match = m.group();
						orgName = match.replaceAll("\\n", "");
					}
					d.setCdnServer(netName.length() > 0 ? netName.replace(
							"NetName:", "").trim() : "");

					if (!existIP) {
						// Save IPRange to database
						ipRange = new IPRange();
						netRange = netRange.replace("NetRange:", "");
						if (netRange.length() > 0) {
							String minIP = "";
							String maxIP = "";
							String[] tempArray = netRange.split("-");
							if (tempArray != null && tempArray.length == 2) {
								minIP = tempArray[0].trim();
								maxIP = tempArray[1].trim();
							}
							if (minIP.length() > 0 && maxIP.length() > 0) {
								Double min = Utils.ipToLong(minIP);
								Double max = Utils.ipToLong(maxIP);
								if (min != 0 && max != 0) {
									ipRange.setMin(min);
									ipRange.setMax(max);
									ipRange.setWhois(whoisByIPResult);
									ipRange.setId(netRange.replace(" ", ""));
									DS_IPRangeModel.insertDatastore(ipRange);
									JavaCommandLineServiceAccounts.insertIPRange(ipRange); 
									// Save Database
								}
							}
						}
					}
				}
			}
		}
	}
}
